home *** CD-ROM | disk | FTP | other *** search
/ Space & Astronomy / Space and Astronomy (October 1993).iso / mac / VIEWERS / X11 / XLOADIMG.TAR / rlelib.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  48KB  |  1,710 lines

  1. /*
  2.  *    Utah RLE Toolkit library routines.
  3.  * 
  4.  *     Read image support only.
  5.  * 
  6.  *     Cobbled from Utah RLE include and library source files.
  7.  * 
  8.  *     By Graeme Gill
  9.  *     30/5/90
  10.  *
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include <varargs.h>
  16. #include <ctype.h>
  17.  
  18. #include "image.h"        /* need ZFILE definition */
  19. #include "rle.h"
  20.  
  21. /* SUPPRESS 530y */
  22. /* SUPPRESS 558 */
  23. /* SUPPRESS 590 */
  24.  
  25. #define zeof(zfp) feof((zfp)->stream)
  26. #define zclearerr(zfp) clearerr((zfp)->stream)
  27.  
  28. /*
  29.  * This software is copyrighted as noted below.  It may be freely copied,
  30.  * modified, and redistributed, provided that the copyright notice is 
  31.  * preserved on all copies.
  32.  * 
  33.  * There is no warranty or other guarantee of fitness for this software,
  34.  * it is provided solely "as is".  Bug reports or fixes may be sent
  35.  * to the author, who may or may not act on them as he desires.
  36.  *
  37.  * You may not include this software in a program or other software product
  38.  * without supplying the source, or without informing the end-user that the 
  39.  * source is available for no extra charge.
  40.  *
  41.  * If you modify this software, you should include a notice giving the
  42.  * name of the person performing the modification, the date of modification,
  43.  * and the reason for such modification.
  44.  */
  45. /* 
  46.  * Runsv.h - Definitions for Run Length Encoding.
  47.  * 
  48.  * Author:    Spencer W. Thomas
  49.  *         Computer Science Dept.
  50.  *         University of Utah
  51.  * Date:    Mon Aug  9 1982
  52.  * Copyright (c) 1982 Spencer W. Thomas
  53.  */
  54.  
  55. #ifndef XTNDRUNSV
  56. #define XTNDRUNSV
  57.  
  58. /* 
  59.  * Opcode definitions
  60.  */
  61.  
  62. #define     LONG                0x40
  63. #define        RSkipLinesOp    1
  64. #define        RSetColorOp        2
  65. #define        RSkipPixelsOp    3
  66. #define        RByteDataOp        5
  67. #define        RRunDataOp        6
  68. #define        REOFOp        7
  69.  
  70. #define     H_CLEARFIRST        0x1    /* clear framebuffer flag */
  71. #define        H_NO_BACKGROUND    0x2    /* if set, no bg color supplied */
  72. #define        H_ALPHA        0x4   /* if set, alpha channel (-1) present */
  73. #define        H_COMMENT        0x8    /* if set, comments present */
  74.  
  75. struct XtndRsetup
  76. {
  77.     short   h_xpos,
  78.             h_ypos,
  79.             h_xlen,
  80.             h_ylen;
  81.     char    h_flags,
  82.             h_ncolors,
  83.         h_pixelbits,
  84.         h_ncmap,
  85.         h_cmaplen;
  86. };
  87. #define        SETUPSIZE    ((4*2)+5)
  88.  
  89. /* "Old" RLE format magic numbers */
  90. #define        RMAGIC    ('R' << 8)    /* top half of magic number */
  91. #define        WMAGIC    ('W' << 8)    /* black&white rle image */
  92.  
  93. #define        XtndRMAGIC    ((short)0xcc52)    /* RLE file magic number */
  94.  
  95. #endif /* XTNDRUNSV */
  96.  
  97. /*  "svfb.h" */
  98. /*
  99.  * This software is copyrighted as noted below.  It may be freely copied,
  100.  * modified, and redistributed, provided that the copyright notice is 
  101.  * preserved on all copies.
  102.  * 
  103.  * There is no warranty or other guarantee of fitness for this software,
  104.  * it is provided solely "as is".  Bug reports or fixes may be sent
  105.  * to the author, who may or may not act on them as he desires.
  106.  *
  107.  * You may not include this software in a program or other software product
  108.  * without supplying the source, or without informing the end-user that the 
  109.  * source is available for no extra charge.
  110.  *
  111.  * If you modify this software, you should include a notice giving the
  112.  * name of the person performing the modification, the date of modification,
  113.  * and the reason for such modification.
  114.  */
  115. /* 
  116.  * svfb.h - Definitions and a few global variables for svfb.
  117.  * 
  118.  * Author:    Spencer W. Thomas
  119.  *         Computer Science Dept.
  120.  *         University of Utah
  121.  * Date:    Mon Aug  9 1982
  122.  * Copyright (c) 1982 Spencer W. Thomas
  123.  */
  124.  
  125. /* ****************************************************************
  126.  * Dispatch table for different output types.
  127.  */
  128. typedef void sv_fn();
  129. struct sv_dispatch_tab {
  130.     char   *magic;            /* magic type flags */
  131.     sv_fn  *setup,            /* startup function */
  132.        *skipBlankLines,
  133.        *setColor,
  134.        *skipPixels,
  135.        *newScanLine,
  136.        *putdat,            /* put a set of differing pixels */
  137.        *putrn,            /* put a run all the same */
  138.        *blockHook,            /* hook called at start of new */
  139.                     /* output block */
  140.        *putEof;        /* write EOF marker (if possible) */
  141. };
  142.  
  143. struct sv_dispatch_tab sv_DTable[];
  144.  
  145. /* 
  146.  * These definitions presume the existence of a variable called
  147.  * "fileptr", declared "long * fileptr".  *fileptr should be
  148.  * initialized to 0 before calling Setup().
  149.  * A pointer "globals" declared "struct sv_globals * globals" is also
  150.  * presumed to exist.
  151.  */
  152. #define        sv_magic        (sv_DTable[(int)globals->sv_dispatch].magic)
  153. #define        Setup()        (*sv_DTable[(int)globals->sv_dispatch].setup)(globals)
  154. #define        SkipBlankLines(n)    (*sv_DTable[(int)globals->sv_dispatch].skipBlankLines)(n, globals)
  155. #define        SetColor(c)        (*sv_DTable[(int)globals->sv_dispatch].setColor)(c, globals)
  156. #define        SkipPixels(n, l, r)    (*sv_DTable[(int)globals->sv_dispatch].skipPixels)(n,l,r, globals)
  157. #define        NewScanLine(flag)    (*sv_DTable[(int)globals->sv_dispatch].newScanLine)(flag, globals)
  158. #define        putdata(buf, len)    (*sv_DTable[(int)globals->sv_dispatch].putdat)(buf, len, globals)
  159. #define        putrun(val, len, f)    (*sv_DTable[(int)globals->sv_dispatch].putrn)(val,len,f, globals)
  160. #define        BlockHook()        (*sv_DTable[(int)globals->sv_dispatch].blockHook)(globals)
  161. #define        PutEof()        (*sv_DTable[(int)globals->sv_dispatch].putEof)(globals)
  162.  
  163. /* 
  164.  * States for run detection
  165.  */
  166. #define    DATA    0
  167. #define    RUN2    1
  168. #define RUN3    2
  169. #define    RUN4    3
  170. #define    INRUN    -1
  171.  
  172. /*
  173.  * This software is copyrighted as noted below.  It may be freely copied,
  174.  * modified, and redistributed, provided that the copyright notice is 
  175.  * preserved on all copies.
  176.  * 
  177.  * There is no warranty or other guarantee of fitness for this software,
  178.  * it is provided solely "as is".  Bug reports or fixes may be sent
  179.  * to the author, who may or may not act on them as he desires.
  180.  *
  181.  * You may not include this software in a program or other software product
  182.  * without supplying the source, or without informing the end-user that the 
  183.  * source is available for no extra charge.
  184.  *
  185.  * If you modify this software, you should include a notice giving the
  186.  * name of the person performing the modification, the date of modification,
  187.  * and the reason for such modification.
  188.  *
  189.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  190.  *  to have all "void" functions so declared.
  191.  */
  192. /* 
  193.  * svfb_global.c - Global variable initialization for svfb routines.
  194.  * 
  195.  * Author:    Spencer W. Thomas
  196.  *         Computer Science Dept.
  197.  *         University of Utah
  198.  * Date:    Thu Apr 25 1985
  199.  * Copyright (c) 1985,1986 Spencer W. Thomas
  200.  */
  201.  
  202.  
  203. void    RunSetup(),
  204.         RunSkipBlankLines(),
  205.         RunSetColor(),
  206.         RunSkipPixels(),
  207.         RunNewScanLine(),
  208.         Runputdata(),
  209.         Runputrun(),
  210.         RunputEof();
  211.  
  212. void    DefaultBlockHook();
  213. void    NullputEof();
  214.  
  215. struct sv_dispatch_tab sv_DTable[] = {
  216.     {
  217.     " OB",
  218.     RunSetup,
  219.     RunSkipBlankLines,
  220.     RunSetColor,
  221.     RunSkipPixels,
  222.     RunNewScanLine,
  223.     Runputdata,
  224.     Runputrun,
  225.     DefaultBlockHook,
  226.     RunputEof
  227.     },
  228. };
  229.  
  230. static int sv_bg_color[3] = { 0, 0, 0 };
  231.  
  232. struct sv_globals sv_globals = {
  233.     RUN_DISPATCH,        /* dispatch value */
  234.     3,                /* 3 colors */
  235.     sv_bg_color,        /* background color */
  236.     0,                /* (alpha) if 1, save alpha channel */
  237.     2,                /* (background) 0->just save pixels, */
  238.                 /* 1->overlay, 2->clear to bg first */
  239.     0, 511,            /* (xmin, xmax) X bounds to save */
  240.     0, 479,            /* (ymin, ymax) Y bounds to save */
  241.     0,                /* ncmap (if != 0, save color map) */
  242.     8,                /* cmaplen (log2 of length of color map) */
  243.     NULL,            /* pointer to color map */
  244.     NULL,            /* pointer to comment strings */
  245.     NULL,            /* output file */
  246.     { 7 }            /* RGB channels only */
  247.     /* Can't initialize the union */
  248. };
  249.  
  250. /* ARGSUSED */
  251. void
  252. NullputEof(globals)
  253. struct sv_globals * globals;
  254. {
  255.                 /* do nothing */
  256. }
  257.  
  258. /*
  259.  * This software is copyrighted as noted below.  It may be freely copied,
  260.  * modified, and redistributed, provided that the copyright notice is 
  261.  * preserved on all copies.
  262.  * 
  263.  * There is no warranty or other guarantee of fitness for this software,
  264.  * it is provided solely "as is".  Bug reports or fixes may be sent
  265.  * to the author, who may or may not act on them as he desires.
  266.  *
  267.  * You may not include this software in a program or other software product
  268.  * without supplying the source, or without informing the end-user that the 
  269.  * source is available for no extra charge.
  270.  *
  271.  * If you modify this software, you should include a notice giving the
  272.  * name of the person performing the modification, the date of modification,
  273.  * and the reason for such modification.
  274.  *
  275.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  276.  *  to have all "void" functions so declared.
  277.  */
  278. /* 
  279.  * Runsv.c - General purpose Run Length Encoding for svfb.
  280.  * 
  281.  * Author:    Spencer W. Thomas
  282.  *         Computer Science Dept.
  283.  *         University of Utah
  284.  * Date:    Mon Aug  9 1982
  285.  * Copyright (c) 1982,1986 Spencer W. Thomas
  286.  */
  287.  
  288. /* THIS IS WAY OUT OF DATE.  See rle.5.
  289.  * The output file format is:
  290.  * 
  291.  * Word 0:    A "magic" number.  The top byte of the word contains
  292.  *        the letter 'R' or the letter 'W'.  'W' indicates that
  293.  *        only black and white information was saved.  The bottom
  294.  *        byte is one of the following:
  295.  *    ' ':    Means a straight "box" save, -S flag was given.
  296.  *    'B':    Image saved with background color, clear screen to
  297.  *        background before restoring image.
  298.  *    'O':    Image saved in overlay mode.
  299.  * 
  300.  * Words 1-6:    The structure
  301.  * {   short   xpos,            * Lower left corner
  302.  *             ypos,
  303.  *             xsize,            * Size of saved box
  304.  *             ysize;
  305.  *     char    rgb[3];            * Background color
  306.  *     char    map;            * flag for map presence
  307.  * }
  308.  * 
  309.  * If the map flag is non-zero, then the color map will follow as 
  310.  * 3*256 16 bit words, first the red map, then the green map, and
  311.  * finally the blue map.
  312.  * 
  313.  * Following the setup information is the Run Length Encoded image.
  314.  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
  315.  * possibly one or more following words (all words are 16 bits).  The
  316.  * instruction opcodes are:
  317.  * 
  318.  * SkipLines (1):   The bottom 10 bits are an unsigned number to be added to
  319.  *            current Y position.
  320.  * 
  321.  * SetColor (2):    The datum indicates which color is to be loaded with
  322.  *             the data described by the following ByteData and
  323.  *             RunData instructions.  0->red, 1->green, 2->blue.  The
  324.  *             operation also resets the X position to the initial
  325.  *             X (i.e. a carriage return operation is performed).
  326.  * 
  327.  * SkipPixels (3):  The bottom 10 bits are an unsigned number to be
  328.  *             added to the current X position.
  329.  * 
  330.  * ByteData (5):    The datum is one less than the number of bytes of
  331.  *             color data following.  If the number of bytes is
  332.  *             odd, a filler byte will be appended to the end of
  333.  *             the byte string to make an integral number of 16-bit
  334.  *             words.  The bytes are in PDP-11 order.  The X
  335.  *             position is incremented to follow the last byte of
  336.  *             data.
  337.  * 
  338.  * RunData (6):        The datum is one less than the run length.  The
  339.  *             following word contains (in its lower 8 bits) the
  340.  *             color of the run.  The X position is incremented to
  341.  *             follow the last byte in the run.
  342.  */
  343.  
  344. #define UPPER 255            /* anything bigger ain't a byte */
  345.  
  346. /* Predefine LITTLE_ENDIAN for vax and pdp11 machines */
  347. #if defined(vax) || defined(pdp11)
  348. #define LITTLE_ENDIAN
  349. #endif
  350.  
  351. /*
  352.  * Macros to make writing instructions with correct byte order easier.
  353.  */
  354. union { short s; char c[2]; } arg;
  355. #ifdef LITTLE_ENDIAN
  356. #define    put16(a)    arg.s=a,putc(arg.c[0],sv_fd), putc(arg.c[1],sv_fd)
  357. #else
  358. #define    put16(a)    arg.s=a,putc(arg.c[1],sv_fd), putc(arg.c[0],sv_fd)
  359. #endif
  360.  
  361. /* short instructions */
  362. #define mk_short_1(oper,a1)        /* one argument short */ \
  363.     putc(oper,sv_fd), putc((char)a1,sv_fd)
  364.  
  365. #define mk_short_2(oper,a1,a2)        /* two argument short */ \
  366.     putc(oper,sv_fd), putc((char)a1,sv_fd), put16(a2)
  367.  
  368. /* long instructions */
  369. #define mk_long_1(oper,a1)        /* one argument long */ \
  370.     putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), put16(a1)
  371.  
  372. #define mk_long_2(oper,a1,a2)        /* two argument long */ \
  373.     putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), \
  374.     put16(a1), put16(a2)
  375.  
  376. /* choose between long and short format instructions */
  377. /* NOTE: these macros can only be used where a STATEMENT is legal */
  378.  
  379. #define mk_inst_1(oper,a1)        /* one argument inst */ \
  380.     if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
  381.  
  382. #define mk_inst_2(oper,a1,a2)        /* two argument inst */ \
  383.     if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
  384.  
  385. /* 
  386.  * Opcode definitions
  387.  */
  388. #define        RSkipLines(n)           mk_inst_1(RSkipLinesOp,(n))
  389.  
  390. #define        RSetColor(c)        mk_short_1(RSetColorOp,(c))
  391.                     /* has side effect of performing */
  392.                     /* "carriage return" action */
  393.  
  394. #define        RSkipPixels(n)        mk_inst_1(RSkipPixelsOp,(n))
  395.  
  396. #define        RNewLine            RSkipLines(1)
  397.  
  398. #define        RByteData(n)        mk_inst_1(RByteDataOp,n)
  399.                     /* followed by ((n+1)/2)*2 bytes */
  400.                     /* of data.  If n is odd, last */
  401.                     /* byte will be ignored */
  402.                     /* "cursor" is left at pixel */
  403.                     /* following last pixel written */
  404.  
  405. #define        RRunData(n,c)        mk_inst_2(RRunDataOp,(n),(c))
  406.                     /* next word contains color data */
  407.                     /* "cursor" is left at pixel after */
  408.                     /* end of run */
  409.  
  410. #define     REOF            mk_inst_1(REOFOp,0)
  411.                     /* Really opcode only */
  412.  
  413. /*****************************************************************
  414.  * TAG( RunSetup )
  415.  * Put out initial setup data for RLE svfb files.
  416.  */
  417. void
  418. RunSetup(globals)
  419. register struct sv_globals * globals;
  420. {
  421. }
  422.  
  423. /*****************************************************************
  424.  * TAG( RunSkipBlankLines )
  425.  * Skip one or more blank lines in the RLE file.
  426.  */
  427. void
  428. RunSkipBlankLines(nblank, globals)
  429. register struct sv_globals * globals;
  430. {
  431. }
  432.  
  433. /*****************************************************************
  434.  * TAG( RunSetColor )
  435.  * Select a color and do carriage return.
  436.  * color: 0 = Red, 1 = Green, 2 = Blue.
  437.  */
  438. void
  439. RunSetColor(c, globals)
  440. register struct sv_globals * globals;
  441. {
  442. }
  443.  
  444. /*****************************************************************
  445.  * TAG( RunSkipPixels )
  446.  * Skip a run of background.
  447.  */
  448.  
  449. /* ARGSUSED */
  450. void
  451. RunSkipPixels(nskip, last, wasrun, globals)
  452. register struct sv_globals * globals;
  453. {
  454. }
  455.  
  456. /*****************************************************************
  457.  * TAG( RunNewScanLine )
  458.  * Perform a newline action.  Since CR is implied by the Set Color
  459.  * operation, only generate code if the newline flag is true.
  460.  */
  461. void
  462. RunNewScanLine(flag, globals)
  463. register struct sv_globals * globals;
  464. {
  465. }
  466.  
  467. /*****************************************************************
  468.  * TAG( Runputdata )
  469.  * Put one or more pixels of byte data into the output file.
  470.  */
  471. void
  472. Runputdata(buf, n, globals)
  473. rle_pixel * buf;
  474. register struct sv_globals * globals;
  475. {
  476. }
  477.  
  478. /*****************************************************************
  479.  * TAG( Runputrun )
  480.  * Output a single color run.
  481.  */
  482.  
  483. /* ARGSUSED */
  484. void
  485. Runputrun(color, n, last, globals)
  486. register struct sv_globals * globals;
  487. {
  488. }
  489.  
  490.  
  491. /*****************************************************************
  492.  * TAG( RunputEof )
  493.  * Output an EOF opcode
  494.  */
  495. void
  496. RunputEof( globals )
  497. register struct sv_globals * globals;
  498. {
  499. }
  500.  
  501. /*ARGSUSED*/
  502. void
  503. DefaultBlockHook(globals)
  504. struct sv_globals * globals;
  505. {
  506. }
  507.  
  508.  
  509. /*
  510.  * This software is copyrighted as noted below.  It may be freely copied,
  511.  * modified, and redistributed, provided that the copyright notice is 
  512.  * preserved on all copies.
  513.  * 
  514.  * There is no warranty or other guarantee of fitness for this software,
  515.  * it is provided solely "as is".  Bug reports or fixes may be sent
  516.  * to the author, who may or may not act on them as he desires.
  517.  *
  518.  * You may not include this software in a program or other software product
  519.  * without supplying the source, or without informing the end-user that the 
  520.  * source is available for no extra charge.
  521.  *
  522.  * If you modify this software, you should include a notice giving the
  523.  * name of the person performing the modification, the date of modification,
  524.  * and the reason for such modification.
  525.  */
  526. /* 
  527.  * buildmap.c - Build a color map from the RLE file color map.
  528.  * 
  529.  * Author:    Spencer W. Thomas
  530.  *         Computer Science Dept.
  531.  *         University of Utah
  532.  * Date:    Sat Jan 24 1987
  533.  * Copyright (c) 1987, University of Utah
  534.  */
  535.  
  536. /*****************************************************************
  537.  * TAG( buildmap )
  538.  * 
  539.  * Returns a color map that can easily be used to map the pixel values in
  540.  * an RLE file.  Map is built from the color map in the input file.
  541.  * Inputs:
  542.  *     globals:    sv_globals structure containing color map.
  543.  *    minmap:        Minimum number of channels in output map.
  544.  *    gamma:        Adjust color map for this image gamma value
  545.  *            (1.0 means no adjustment).
  546.  * Outputs:
  547.  *     Returns an array of pointers to arrays of rle_pixels.  The array
  548.  *    of pointers contains max(sv_ncolors, sv_ncmap) elements, each 
  549.  *    array of pixels contains 2^sv_cmaplen elements.  The pixel arrays
  550.  *    should be considered read-only.
  551.  * Assumptions:
  552.  *     [None]
  553.  * Algorithm:
  554.  *    Ensure that there are at least sv_ncolors rows in the map, and
  555.  *    that each has at least 256 elements in it (largest map that can
  556.  *    be addressed by an rle_pixel).
  557.  */
  558. rle_pixel **
  559. buildmap( globals, minmap, gamma )
  560. struct sv_globals *globals;
  561. int minmap;
  562. double gamma;
  563. {
  564.     rle_pixel ** cmap, * gammap;
  565.     register int i, j;
  566.     int maplen, cmaplen, ncmap, nmap;
  567.  
  568.     if ( globals->sv_ncmap == 0 )    /* make identity map */
  569.     {
  570.     nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap;
  571.     cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  572.     cmap[0] = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) );
  573.     for ( i = 0; i < 256; i++ )
  574.         cmap[0][i] = i;
  575.     for ( i = 1; i < nmap; i++ )
  576.         cmap[i] = cmap[0];
  577.     maplen = 256;
  578.     ncmap = 1;        /* number of unique rows */
  579.     }
  580.     else            /* make map from globals */
  581.     {
  582.     /* Map is at least 256 long */
  583.     cmaplen = (1 << globals->sv_cmaplen);
  584.     if ( cmaplen < 256 )
  585.         maplen = 256;
  586.     else
  587.         maplen = cmaplen;
  588.  
  589.     if ( globals->sv_ncmap == 1 )    /* make "b&w" map */
  590.     {
  591.         nmap = (minmap < globals->sv_ncolors) ?
  592.         globals->sv_ncolors : minmap;
  593.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  594.         cmap[0] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  595.         for ( i = 0; i < maplen; i++ )
  596.         if ( i < cmaplen )
  597.             cmap[0][i] = globals->sv_cmap[i] >> 8;
  598.         else
  599.             cmap[0][i] = i;
  600.         for ( i = 1; i < nmap; i++ )
  601.         cmap[i] = cmap[0];
  602.         ncmap = 1;
  603.     }
  604.     else if ( globals->sv_ncolors <= globals->sv_ncmap )
  605.     {
  606.         nmap = (minmap < globals->sv_ncmap) ? globals->sv_ncmap : minmap;
  607.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  608.         for ( j = 0; j < globals->sv_ncmap; j++ )
  609.         {
  610.         cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  611.         for ( i = 0; i < maplen; i++ )
  612.             if ( i < cmaplen )
  613.             cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8;
  614.             else
  615.             cmap[j][i] = i;
  616.         }
  617.         for ( i = j, j--; i < nmap; i++ )
  618.         cmap[i] = cmap[j];
  619.         ncmap = globals->sv_ncmap;
  620.     }
  621.     else            /* ncolors > ncmap */
  622.     {
  623.         nmap = (minmap < globals->sv_ncolors) ?
  624.         globals->sv_ncolors : minmap;
  625.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  626.         for ( j = 0; j < globals->sv_ncmap; j++ )
  627.         {
  628.         cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  629.         for ( i = 0; i < maplen; i++ )
  630.             if ( i < cmaplen )
  631.             cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8;
  632.             else
  633.             cmap[j][i] = i;
  634.         }
  635.         for( i = j, j--; i < nmap; i++ )
  636.         cmap[i] = cmap[j];
  637.         ncmap = globals->sv_ncmap;
  638.     }
  639.     }
  640.         
  641.     /* Gamma compensate if requested */
  642.     if ( gamma != 1.0 )
  643.     {
  644.     gammap = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) );
  645.     for ( i = 0; i < 256; i++ )
  646.         {
  647. #ifdef BYTEBUG
  648.         int byteb1;
  649.         byteb1 = (int)(0.5 + 255.0 * pow( i / 255.0, gamma ));
  650.         gammap[i] = byteb1;
  651. #else
  652.         gammap[i] = (int)(0.5 + 255.0 * pow( i / 255.0, gamma ));
  653. #endif
  654.         }
  655.     for ( i = 0; i < ncmap; i++ )
  656.         for ( j = 0; j < maplen; j++ )
  657.         cmap[i][j] = gammap[cmap[i][j]];
  658.     }
  659.  
  660.     return cmap;
  661. }
  662.  
  663. /*
  664.  * This software is copyrighted as noted below.  It may be freely copied,
  665.  * modified, and redistributed, provided that the copyright notice is 
  666.  * preserved on all copies.
  667.  * 
  668.  * There is no warranty or other guarantee of fitness for this software,
  669.  * it is provided solely "as is".  Bug reports or fixes may be sent
  670.  * to the author, who may or may not act on them as he desires.
  671.  *
  672.  * You may not include this software in a program or other software product
  673.  * without supplying the source, or without informing the end-user that the 
  674.  * source is available for no extra charge.
  675.  *
  676.  * If you modify this software, you should include a notice giving the
  677.  * name of the person performing the modification, the date of modification,
  678.  * and the reason for such modification.
  679.  */
  680. /* 
  681.  * rle_getcom.c - Get specific comments from globals structure.
  682.  * 
  683.  * Author:    Spencer W. Thomas
  684.  *         Computer Science Dept.
  685.  *         University of Utah
  686.  * Date:    Sun Jan 25 1987
  687.  * Copyright (c) 1987, University of Utah
  688.  */
  689.  
  690. /*****************************************************************
  691.  * TAG( match )
  692.  * 
  693.  * Match a name against a test string for "name=value" or "name".
  694.  * If it matches name=value, return pointer to value part, if just
  695.  * name, return pointer to NUL at end of string.  If no match, return NULL.
  696.  *
  697.  * Inputs:
  698.  *     n:    Name to match.  May also be "name=value" to make it easier
  699.  *        to replace comments.
  700.  *    v:    Test string.
  701.  * Outputs:
  702.  *     Returns pointer as above.
  703.  * Assumptions:
  704.  *    [None]
  705.  * Algorithm:
  706.  *    [None]
  707.  */
  708. static char *
  709. match( n, v )
  710. register char *n;
  711. register char *v;
  712. {
  713.     for ( ; *n != '\0' && *n != '=' && *n == *v; n++, v++ )
  714.     ;
  715.     if (*n == '\0' || *n == '=')
  716.     if ( *v == '\0' )
  717.         return v;
  718.     else if ( *v == '=' )
  719.         return ++v;
  720.  
  721.     return NULL;
  722. }
  723.  
  724. /*****************************************************************
  725.  * TAG( rle_getcom )
  726.  * 
  727.  * Return a pointer to the value part of a name=value pair in the comments.
  728.  * Inputs:
  729.  *     name:        Name part of the comment to search for.
  730.  *    globals:    sv_globals structure.
  731.  * Outputs:
  732.  *     Returns pointer to value part of comment or NULL if no match.
  733.  * Assumptions:
  734.  *    [None]
  735.  * Algorithm:
  736.  *    [None]
  737.  */
  738. char *
  739. rle_getcom( name, globals )
  740. char *name;
  741. struct sv_globals *globals;
  742. {
  743.     char ** cp;
  744.     char * v;
  745.  
  746.     if ( globals->sv_comments == NULL )
  747.     return NULL;
  748.  
  749.     for ( cp = globals->sv_comments; *cp; cp++ )
  750.     if ( (v = match( name, *cp )) != NULL )
  751.         return v;
  752.  
  753.     return NULL;
  754. }
  755.  
  756. /*
  757.  * This software is copyrighted as noted below.  It may be freely copied,
  758.  * modified, and redistributed, provided that the copyright notice is 
  759.  * preserved on all copies.
  760.  * 
  761.  * There is no warranty or other guarantee of fitness for this software,
  762.  * it is provided solely "as is".  Bug reports or fixes may be sent
  763.  * to the author, who may or may not act on them as he desires.
  764.  *
  765.  * You may not include this software in a program or other software product
  766.  * without supplying the source, or without informing the end-user that the 
  767.  * source is available for no extra charge.
  768.  *
  769.  * If you modify this software, you should include a notice giving the
  770.  * name of the person performing the modification, the date of modification,
  771.  * and the reason for such modification.
  772.  *
  773.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  774.  *  to have all "void" functions so declared.
  775.  */
  776. /* 
  777.  * rle_getrow.c - Read an RLE file in.
  778.  * 
  779.  * Author:    Spencer W. Thomas
  780.  *         Computer Science Dept.
  781.  *         University of Utah
  782.  * Date:    Wed Apr 10 1985
  783.  * Copyright (c) 1985 Spencer W. Thomas
  784.  * 
  785.  */
  786. /*
  787.  * Automatically define LITTLE_ENDIAN on vax and pdp11 machines
  788.  */
  789. #if defined(vax) || defined(pdp11)
  790. #define    LITTLE_ENDIAN
  791. #endif
  792.  
  793. struct inst {
  794.   unsigned opcode:8, datum:8;
  795. };
  796.  
  797. #define BREAD(type, var, len)\
  798.         zread( infile, (byte *)&var,len )
  799. #define OPCODE(inst) (inst.opcode & ~LONG)
  800. #define LONGP(inst) (inst.opcode & LONG)
  801. #define DATUM(inst) (0x00ff & inst.datum)
  802.  
  803. static int       debug_f;        /* if non-zero, print debug info */
  804. static void    bfill();
  805.  
  806. /*****************************************************************
  807.  * TAG( rle_get_setup )
  808.  * 
  809.  * Read the initialization information from an RLE file.
  810.  * Inputs:
  811.  *     globals:    Contains pointer to the input file.
  812.  * Outputs:
  813.  *     globals:    Initialized with information from the
  814.  *            input file.
  815.  *    Returns 0 on success, -1 if the file is not an RLE file,
  816.  *    -2 if malloc of the color map failed, -3 if an immediate EOF
  817.  *    is hit (empty input file), and -4 if an EOF is encountered reading
  818.  *    the setup information.
  819.  * Assumptions:
  820.  *     infile points to the "magic" number in an RLE file (usually
  821.  * byte 0 in the file).
  822.  * Algorithm:
  823.  *     Read in the setup info and fill in sv_globals.
  824.  */
  825. rle_get_setup( globals )
  826. struct sv_globals * globals;
  827. {
  828.     struct XtndRsetup setup;
  829.     short magic;            /* assume 16 bits */
  830.     register ZFILE *infile = globals->svfb_fd;
  831.     rle_pixel * bg_color;
  832.     register int i;
  833.     char * comment_buf;
  834.  
  835.     zclearerr(infile);
  836.     BREAD( short, magic, sizeof magic );
  837.     SWAB(magic);
  838.     if ( zeof( infile ) )
  839.     return -3;
  840.     if ( magic != XtndRMAGIC )
  841.     return -1;
  842.     BREAD( struct XtndRsetup, setup, SETUPSIZE );  /* assume VAX packing */
  843.     if ( zeof( infile ) )
  844.     return -4;
  845.     SWAB( setup.h_xpos );
  846.     SWAB( setup.h_ypos );
  847.     SWAB( setup.h_xlen );
  848.     SWAB( setup.h_ylen );
  849.  
  850.     /* Extract information from setup */
  851.     globals->sv_ncolors = setup.h_ncolors;
  852.     for ( i = 0; i < globals->sv_ncolors; i++ )
  853.     SV_SET_BIT( *globals, i );
  854.  
  855.     if ( !(setup.h_flags & H_NO_BACKGROUND) )
  856.     {
  857.     globals->sv_bg_color = (int *)lmalloc(
  858.         (unsigned)(sizeof(int) * setup.h_ncolors) );
  859.     bg_color = (rle_pixel *)lmalloc(
  860.         (unsigned)(1 + (setup.h_ncolors / 2) * 2) );
  861.     zread( infile, (byte *)bg_color, 1 + (setup.h_ncolors / 2) * 2 );
  862.     for ( i = 0; i < setup.h_ncolors; i++ )
  863.         globals->sv_bg_color[i] = bg_color[i];
  864.     lfree( bg_color );
  865.     }
  866.     else
  867.     zgetc( infile );            /* skip filler byte */
  868.  
  869.     if ( setup.h_flags & H_NO_BACKGROUND )
  870.     globals->sv_background = 0;
  871.     else if ( setup.h_flags & H_CLEARFIRST )
  872.     globals->sv_background = 2;
  873.     else
  874.     globals->sv_background = 1;
  875.     if ( setup.h_flags & H_ALPHA )
  876.     {
  877.     globals->sv_alpha = 1;
  878.     SV_SET_BIT( *globals, SV_ALPHA );
  879.     }
  880.     else
  881.     globals->sv_alpha = 0;
  882.  
  883.     globals->sv_xmin = setup.h_xpos;
  884.     globals->sv_ymin = setup.h_ypos;
  885.     globals->sv_xmax = globals->sv_xmin + setup.h_xlen - 1;
  886.     globals->sv_ymax = globals->sv_ymin + setup.h_ylen - 1;
  887.  
  888.     globals->sv_ncmap = setup.h_ncmap;
  889.     globals->sv_cmaplen = setup.h_cmaplen;
  890.     if ( globals->sv_ncmap > 0 )
  891.     {
  892.     register int maplen =
  893.              globals->sv_ncmap * (1 << globals->sv_cmaplen);
  894.     globals->sv_cmap = (rle_map *)lmalloc(
  895.         (unsigned)(sizeof(rle_map) * maplen) );
  896.     if ( globals->sv_cmap == NULL )
  897.     {
  898.         fprintf( stderr,
  899.         "Malloc failed for color map of size %d*%d in rle_get_setup\n",
  900.         globals->sv_ncmap, (1 << globals->sv_cmaplen) );
  901.         return -2;
  902.     }
  903.     zread( infile, (byte *)globals->sv_cmap, sizeof(short) * maplen );
  904. #ifndef LITTLE_ENDIAN
  905.         /* Swap bytes on bigendian machines
  906.      */
  907.         for ( i = 0; i < maplen; i++ )
  908.             SWAB( globals->sv_cmap[i] );
  909. #endif
  910.     }
  911.  
  912.     /* Check for comments */
  913.     if ( setup.h_flags & H_COMMENT )
  914.     {
  915.     short comlen, evenlen;
  916.     register char * cp;
  917.  
  918.     BREAD( short, comlen, sizeof comlen );    /* get comment length */
  919.     SWAB( comlen );
  920.     evenlen = (comlen + 1) & ~1;    /* make it even */
  921.     comment_buf = (char *)lmalloc( (unsigned) evenlen );
  922.     if ( comment_buf == NULL )
  923.     {
  924.         fprintf( stderr,
  925.              "Malloc failed for comment buffer of size %d in rle_get_setup\n",
  926.              comlen );
  927.         return -2;
  928.     }
  929.     zread( infile, (byte *)comment_buf, evenlen );
  930.     /* Count the comments */
  931.     for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ )
  932.         if ( *cp == 0 )
  933.         i++;
  934.     i++;            /* extra for NULL pointer at end */
  935.     /* Get space to put pointers to comments */
  936.     globals->sv_comments =
  937.         (char **)lmalloc( (unsigned)(i * sizeof(char *)) );
  938.     if ( globals->sv_comments == NULL )
  939.     {
  940.         fprintf( stderr,
  941.             "Malloc failed for %d comment pointers in rle_get_setup\n",
  942.              i );
  943.         return -2;
  944.     }
  945.     /* Get pointers to the comments */
  946.     *globals->sv_comments = comment_buf;
  947.     for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ )
  948.         if ( *(cp - 1) == 0 )
  949.         globals->sv_comments[i++] = cp;
  950.     globals->sv_comments[i] = NULL;
  951.     }
  952.     else
  953.     globals->sv_comments = NULL;
  954.  
  955.     /* Initialize state for rle_getrow */
  956.     globals->sv_private.get.scan_y = globals->sv_ymin;
  957.     globals->sv_private.get.vert_skip = 0;
  958.     globals->sv_private.get.is_eof = 0;
  959.     globals->sv_private.get.is_seek = 0;    /* Can't do seek on zfile */
  960.     debug_f = 0;
  961.  
  962.     if ( !zeof( infile ) )
  963.     return 0;            /* success! */
  964.     else
  965.     {
  966.     globals->sv_private.get.is_eof = 1;
  967.     return -4;
  968.     }
  969. }
  970.  
  971.  
  972. /*****************************************************************
  973.  * TAG( rle_get_error )
  974.  * 
  975.  * Print an error message for the return code from rle_get_setup
  976.  * Inputs:
  977.  *     code:        The return code from rle_get_setup.
  978.  *    pgmname:    Name of this program (argv[0]).
  979.  *    fname:        Name of the input file.
  980.  * Outputs:
  981.  *     Prints an error message on standard output.
  982.  *    Returns code.
  983.  */
  984.  
  985. rle_get_error( code, pgmname, fname )
  986. char *pgmname;
  987. char *fname;
  988. {
  989.     switch( code )
  990.     {
  991.     case 0:            /* success */
  992.     break;
  993.  
  994.     case -1:            /* Not an RLE file */
  995.     fprintf( stderr, "%s: %s is not an RLE file\n",
  996.          pgmname, fname );
  997.     break;
  998.  
  999.     case -2:            /* malloc failed */
  1000.     fprintf( stderr,
  1001.          "%s: Malloc failed reading header of file %s\n",
  1002.          pgmname, fname );
  1003.     break;
  1004.  
  1005.     case -3:
  1006.     fprintf( stderr, "%s: %s is an empty file\n", pgmname, fname );
  1007.     break;
  1008.  
  1009.     case -4:
  1010.     fprintf( stderr,
  1011.          "%s: RLE header of %s is incomplete (premature EOF)\n",
  1012.          pgmname, fname );
  1013.     break;
  1014.  
  1015.     default:
  1016.     fprintf( stderr, "%s: Error encountered reading header of %s\n",
  1017.          pgmname, fname );
  1018.     break;
  1019.     }
  1020.     return code;
  1021. }
  1022.  
  1023.  
  1024. /*****************************************************************
  1025.  * TAG( rle_get_setup_ok )
  1026.  * 
  1027.  * Read the initialization information from an RLE file.
  1028.  * Inputs:
  1029.  *     globals:    Contains pointer to the input file.
  1030.  *    prog_name:  Program name to be printed in the error message.
  1031.  *      file_name:  File name to be printed in the error message.
  1032.  *                  If NULL, the string "stdin" is generated.
  1033.  * Outputs:
  1034.  *     globals:    Initialized with information from the
  1035.  *            input file.
  1036.  *      If reading the globals fails, it prints an error message
  1037.  *    and exits with the appropriate status code.
  1038.  * Algorithm:
  1039.  *     sv_get_setup does all the work.
  1040.  */
  1041. void
  1042. rle_get_setup_ok( globals, prog_name, file_name )
  1043. struct sv_globals * globals;
  1044. char *prog_name;
  1045. char *file_name;
  1046. {
  1047.     int code;
  1048.  
  1049.     if (! file_name)
  1050.     file_name = "stdin";
  1051.  
  1052.     code = rle_get_error( rle_get_setup( globals ), prog_name, file_name );
  1053.     if (code)
  1054.     exit( code );
  1055. }
  1056.  
  1057.  
  1058. /*****************************************************************
  1059.  * TAG( rle_debug )
  1060.  * 
  1061.  * Turn RLE debugging on or off.
  1062.  * Inputs:
  1063.  *     on_off:        if 0, stop debugging, else start.
  1064.  * Outputs:
  1065.  *     Sets internal debug flag.
  1066.  * Assumptions:
  1067.  *    [None]
  1068.  * Algorithm:
  1069.  *    [None]
  1070.  */
  1071. void
  1072. rle_debug( on_off )
  1073. int on_off;
  1074. {
  1075.     debug_f = on_off;
  1076. }
  1077.  
  1078.  
  1079. /*****************************************************************
  1080.  * TAG( rle_getrow )
  1081.  * 
  1082.  * Get a scanline from the input file.
  1083.  * Inputs:
  1084.  *    globals:    sv_globals structure containing information about 
  1085.  *            the input file.
  1086.  * Outputs:
  1087.  *     scanline:   an array of pointers to the individual color
  1088.  *            scanlines.  Scanline is assumed to have
  1089.  *            globals->sv_ncolors pointers to arrays of rle_pixel,
  1090.  *            each of which is at least globals->sv_xmax+1 long.
  1091.  *    Returns the current scanline number.
  1092.  * Assumptions:
  1093.  *     rle_get_setup has already been called.
  1094.  * Algorithm:
  1095.  *     If a vertical skip is being executed, and clear-to-background is
  1096.  *    specified (globals->sv_background is true), just set the
  1097.  *    scanlines to the background color.  If clear-to-background is
  1098.  *    not set, just increment the scanline number and return.
  1099.  * 
  1100.  *    Otherwise, read input until a vertical skip is encountered,
  1101.  *    decoding the instructions into scanline data.
  1102.  */
  1103.  
  1104. rle_getrow( globals, scanline )
  1105. struct sv_globals * globals;
  1106. rle_pixel *scanline[];
  1107. {
  1108.     register rle_pixel * scanc;
  1109.     register int nc;
  1110.     register ZFILE *infile = globals->svfb_fd;
  1111.     int scan_x = globals->sv_xmin,    /* current X position */
  1112.        channel = 0;            /* current color channel */
  1113.     short word, long_data;
  1114.     struct inst inst;
  1115.  
  1116.     /* Clear to background if specified */
  1117.     if ( globals->sv_background == 2 )
  1118.     {
  1119.     if ( globals->sv_alpha && SV_BIT( *globals, -1 ) )
  1120.         bfill( (char *)scanline[-1], globals->sv_xmax + 1, 0 );
  1121.     for ( nc = 0; nc < globals->sv_ncolors; nc++ )
  1122.         if ( SV_BIT( *globals, nc ) )
  1123.         bfill( (char *)scanline[nc], globals->sv_xmax+1,
  1124.             globals->sv_bg_color[nc] );
  1125.     }
  1126.  
  1127.     /* If skipping, then just return */
  1128.     if ( globals->sv_private.get.vert_skip > 0 )
  1129.     {
  1130.     globals->sv_private.get.vert_skip--;
  1131.     globals->sv_private.get.scan_y++;
  1132.     if ( globals->sv_private.get.vert_skip > 0 )
  1133.         return globals->sv_private.get.scan_y;
  1134.     }
  1135.  
  1136.     /* If EOF has been encountered, return also */
  1137.     if ( globals->sv_private.get.is_eof )
  1138.     return ++globals->sv_private.get.scan_y;
  1139.  
  1140.     /* Otherwise, read and interpret instructions until a skipLines
  1141.      * instruction is encountered.
  1142.      */
  1143.     if ( SV_BIT( *globals, channel ) )
  1144.     scanc = scanline[channel] + scan_x;
  1145.     else
  1146.     scanc = NULL;
  1147.     for (;;)
  1148.     {
  1149.         BREAD(struct inst, inst, 2 );
  1150.     if ( zeof(infile) )
  1151.     {
  1152.         globals->sv_private.get.is_eof = 1;
  1153.         break;        /* <--- one of the exits */
  1154.     }
  1155.  
  1156.     switch( OPCODE(inst) )
  1157.     {
  1158.     case RSkipLinesOp:
  1159.         if ( LONGP(inst) )
  1160.         {
  1161.             BREAD( short, long_data, sizeof long_data );
  1162.         SWAB( long_data );
  1163.         globals->sv_private.get.vert_skip = long_data;
  1164.         }
  1165.         else
  1166.         globals->sv_private.get.vert_skip = DATUM(inst);
  1167.         if (debug_f)
  1168.         fprintf(stderr, "Skip %d Lines (to %d)\n",
  1169.             globals->sv_private.get.vert_skip,
  1170.             globals->sv_private.get.scan_y +
  1171.                 globals->sv_private.get.vert_skip );
  1172.  
  1173.         break;            /* need to break for() here, too */
  1174.  
  1175.     case RSetColorOp:
  1176.         channel = DATUM(inst);    /* select color channel */
  1177.         if ( channel == 255 )
  1178.         channel = -1;
  1179.         scan_x = globals->sv_xmin;
  1180.         if ( SV_BIT( *globals, channel ) )
  1181.         scanc = scanline[channel]+scan_x;
  1182.         if ( debug_f )
  1183.         fprintf( stderr, "Set color to %d (reset x to %d)\n",
  1184.              channel, scan_x );
  1185.         break;
  1186.  
  1187.     case RSkipPixelsOp:
  1188.         if ( LONGP(inst) )
  1189.         {
  1190.             BREAD( short, long_data, sizeof long_data );
  1191.         SWAB( long_data );
  1192.         scan_x += long_data;
  1193.         scanc += long_data;
  1194.         if ( debug_f )
  1195.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  1196.                 long_data, scan_x );
  1197.              
  1198.         }
  1199.         else
  1200.         {
  1201.         scan_x += DATUM(inst);
  1202.         scanc += DATUM(inst);
  1203.         if ( debug_f )
  1204.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  1205.                 DATUM(inst), scan_x );
  1206.         }
  1207.         break;
  1208.  
  1209.     case RByteDataOp:
  1210.         if ( LONGP(inst) )
  1211.         {
  1212.             BREAD( short, long_data, sizeof long_data );
  1213.         SWAB( long_data );
  1214.         nc = (int)long_data;
  1215.         }
  1216.         else
  1217.         nc = DATUM(inst);
  1218.         nc++;
  1219.         if ( SV_BIT( *globals, channel ) )
  1220.         {
  1221.         zread( infile, (byte *)scanc, nc );
  1222.         if ( nc & 1 )
  1223.             (void)zgetc( infile );    /* throw away odd byte */
  1224.         }
  1225.         else
  1226.         {        /* Emulate a forward fseek */
  1227.             register int ii;
  1228.             for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- )
  1229.             (void) zgetc( infile );    /* discard it */
  1230.         }
  1231.  
  1232.         scanc += nc;
  1233.         scan_x += nc;
  1234.         if ( debug_f )
  1235.         if ( SV_BIT( *globals, channel ) )
  1236.         {
  1237.             rle_pixel * cp = scanc - nc;
  1238.             fprintf( stderr, "Pixel data %d (to %d):", nc, scan_x );
  1239.             for ( ; nc > 0; nc-- )
  1240.             fprintf( stderr, "%02x", *cp++ );
  1241.             putc( '\n', stderr );
  1242.         }
  1243.         else
  1244.         fprintf( stderr, "Pixel data %d (to %d)\n", nc, scan_x );
  1245.         break;
  1246.  
  1247.     case RRunDataOp:
  1248.         if ( LONGP(inst) )
  1249.         {
  1250.             BREAD( short, long_data, sizeof long_data );
  1251.         SWAB( long_data );
  1252.         nc = long_data;
  1253.         }
  1254.         else
  1255.         nc = DATUM(inst);
  1256.         scan_x += nc + 1;
  1257.  
  1258.         BREAD( short, word, sizeof(short) );
  1259.         SWAB( word );
  1260.         if ( debug_f )
  1261.         fprintf( stderr, "Run length %d (to %d), data %02x\n",
  1262.                 nc + 1, scan_x, word );
  1263.         if ( SV_BIT( *globals, channel ) )
  1264.         {
  1265.         if ( nc >= 10 )        /* break point for 785, anyway */
  1266.         {
  1267.             bfill( (char *)scanc, nc + 1, word );
  1268.             scanc += nc + 1;
  1269.         }
  1270.         else
  1271.             for ( ; nc >= 0; nc--, scanc++ )
  1272.             *scanc = word;
  1273.         }
  1274.         break;
  1275.  
  1276.     case REOFOp:
  1277.         globals->sv_private.get.is_eof = 1;
  1278.         break;
  1279.  
  1280.     default:
  1281.         fprintf( stderr,
  1282.              "rle_getrow: Unrecognized opcode: %d\n", inst.opcode );
  1283.         exit(1);
  1284.     }
  1285.     if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp )
  1286.         break;            /* <--- the other loop exit */
  1287.     }
  1288.  
  1289.     return globals->sv_private.get.scan_y;
  1290. }
  1291.  
  1292.  
  1293. /* Fill buffer at s with n copies of character c.  N must be <= 65535*/
  1294. /* ARGSUSED */
  1295. static void bfill( s, n, c )
  1296. char *s;
  1297. int n, c;
  1298. {
  1299. #ifdef vax
  1300.     asm("   movc5   $0,*4(ap),12(ap),8(ap),*4(ap)");
  1301. #else
  1302.     while ( n-- > 0 )
  1303.     *s++ = c;
  1304. #endif
  1305. }
  1306.  
  1307. /*
  1308.  * This software is copyrighted as noted below.  It may be freely copied,
  1309.  * modified, and redistributed, provided that the copyright notice is 
  1310.  * preserved on all copies.
  1311.  * 
  1312.  * There is no warranty or other guarantee of fitness for this software,
  1313.  * it is provided solely "as is".  Bug reports or fixes may be sent
  1314.  * to the author, who may or may not act on them as he desires.
  1315.  *
  1316.  * You may not include this software in a program or other software product
  1317.  * without supplying the source, or without informing the end-user that the 
  1318.  * source is available for no extra charge.
  1319.  *
  1320.  * If you modify this software, you should include a notice giving the
  1321.  * name of the person performing the modification, the date of modification,
  1322.  * and the reason for such modification.
  1323.  *
  1324.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  1325.  *  to have all "void" functions so declared.
  1326.  *
  1327.  * Modified to generate an apropriate size dither map (ie 2x2, 4x4, 8x8
  1328.  * or 16x16) rather than use fixed 16x16 map. Use a large enough map 
  1329.  * to give a minimum of 128 effective levels rather than aiming for 256.
  1330.  * This should give less grainy pictures.
  1331.  * Two global variables can modify this:
  1332.  * dith_levels = 128 (default)
  1333.  * dith_np2 = 0    (default). Nonzero to enable non power of 2 dither mapping.
  1334.  * dith_size = actual dither matrix size chosen.
  1335.  *
  1336.  * Graeme Gill    3 June 88
  1337.  */
  1338.  
  1339. /* 
  1340.  * dither.c - Functions for RGB color dithering.
  1341.  * 
  1342.  * Author:    Spencer W. Thomas
  1343.  *         Computer Science Dept.
  1344.  *         University of Utah
  1345.  * Date:    Mon Feb  2 1987
  1346.  * Copyright (c) 1987, University of Utah
  1347.  */
  1348.  
  1349. void    make_square();
  1350.  
  1351. /* dither globals */
  1352. int dith_levels = 128;
  1353. int dith_np2 = 0;
  1354. int dith_size = 16;
  1355.  
  1356. /* basic dithering macro */
  1357. #define DMAP(v,x,y)    (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])
  1358.  
  1359. /*****************************************************************
  1360.  * TAG( dithermap )
  1361.  * 
  1362.  * Create a color dithering map with a specified number of intensity levels.
  1363.  * Inputs:
  1364.  *     levels:        Intensity levels per primary.
  1365.  *    gamma:        Display gamma value.
  1366.  * Outputs:
  1367.  *     rgbmap:        Generated color map.
  1368.  *    divN:        "div" function for dithering.
  1369.  *    modN:        "mod" function for dithering.
  1370.  * Assumptions:
  1371.  *     rgbmap will hold levels^3 entries.
  1372.  * Algorithm:
  1373.  *    Compute gamma compensation map.
  1374.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  1375.  *    Compute rgbmap with red ramping fastest, green slower, and blue
  1376.  *    slowest (treat it as if it were rgbmap[levels][levels][levels][3]).
  1377.  *    Call make_square to get divN, modN, and magic
  1378.  *
  1379.  * Note:
  1380.  *    Call dithergb( x, y, r, g, b, levels, divN, modN, magic ) to get index
  1381.  *    into rgbmap for a given color/location pair, or use
  1382.  *        row = y % 16; col = x % 16;
  1383.  *        DMAP(v,col,row) =def (divN[v] + (modN[v]>magic[col][row] ? 1 : 0))
  1384.  *        DMAP(r,col,row) + DMAP(g,col,row)*levels + DMAP(b,col,row)*levels^2
  1385.  *    if you don't want function call overhead.
  1386.  */
  1387. void
  1388. dithermap( levels, gamma, rgbmap, divN, modN, magic )
  1389. double gamma;
  1390. int rgbmap[][3];
  1391. int divN[256];
  1392. int modN[256];
  1393. int magic[16][16];
  1394. {
  1395.     double N;
  1396.     register int i;
  1397.     int levelsq, levelsc;
  1398.     int gammamap[256];
  1399.     
  1400.     make_gamma(gamma,gammamap);
  1401.  
  1402.     levelsq = levels*levels;    /* squared */
  1403.     levelsc = levels*levelsq;    /* and cubed */
  1404.  
  1405.     N = 255.0 / (levels - 1);    /* Get size of each step */
  1406.  
  1407.     /* 
  1408.      * Set up the color map entries.
  1409.      */
  1410.     for(i = 0; i < levelsc; i++) {
  1411.     rgbmap[i][0] = gammamap[(int)(0.5 + (i%levels) * N)];
  1412.     rgbmap[i][1] = gammamap[(int)(0.5 + ((i/levels)%levels) * N)];
  1413.     rgbmap[i][2] = gammamap[(int)(0.5 + ((i/levelsq)%levels) * N)];
  1414.     }
  1415.  
  1416.     make_square( N, divN, modN, magic );
  1417. }
  1418.  
  1419.  
  1420. /*****************************************************************
  1421.  * TAG( bwdithermap )
  1422.  * 
  1423.  * Create a color dithering map with a specified number of intensity levels.
  1424.  * Inputs:
  1425.  *     levels:        Intensity levels.
  1426.  *    gamma:        Display gamma value.
  1427.  * Outputs:
  1428.  *     bwmap:        Generated black & white map.
  1429.  *    divN:        "div" function for dithering.
  1430.  *    modN:        "mod" function for dithering.
  1431.  * Assumptions:
  1432.  *     bwmap will hold levels entries.
  1433.  * Algorithm:
  1434.  *    Compute gamma compensation map.
  1435.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  1436.  *    Compute bwmap for levels entries.
  1437.  *    Call make_square to get divN, modN, and magic.
  1438.  * Note:
  1439.  *    Call ditherbw( x, y, val, divN, modN, magic ) to get index into 
  1440.  *    bwmap for a given color/location pair, or use
  1441.  *        row = y % 16; col = x % 16;
  1442.  *        divN[val] + (modN[val]>magic[col][row] ? 1 : 0)
  1443.  *    if you don't want function call overhead.
  1444.  *    On a 1-bit display, use
  1445.  *        divN[val] > magic[col][row] ? 1 : 0
  1446.  */
  1447. void
  1448. bwdithermap( levels, gamma, bwmap, divN, modN, magic )
  1449. double gamma;
  1450. int bwmap[];
  1451. int divN[256];
  1452. int modN[256];
  1453. int magic[16][16];
  1454. {
  1455.     double N;
  1456.     register int i;
  1457.     int gammamap[256];
  1458.     
  1459.     make_gamma(gamma,gammamap);
  1460.  
  1461.     N = 255.0 / (levels - 1);    /* Get size of each step */
  1462.  
  1463.     /* 
  1464.      * Set up the color map entries.
  1465.      */
  1466.     for(i = 0; i < levels; i++)
  1467.     bwmap[i] = gammamap[(int)(0.5 + i * N)];
  1468.  
  1469.     make_square( N, divN, modN, magic );
  1470. }
  1471.  
  1472.  
  1473. /*****************************************************************
  1474.  * TAG( make_square )
  1475.  * 
  1476.  * Build the magic square for a given number of levels.
  1477.  * Inputs:
  1478.  *     N:        Pixel values per level (255.0 / (levels-1)).
  1479.  * (global) dith_levels = 128 (default) - number of effective levels to aim for 
  1480.  * (global) dith_np2 = 0 (default) - non-zero if non power of two size is permissable.
  1481.  * Outputs:
  1482.  *     divN:        Integer value of pixval / N
  1483.  *    modN:        Integer remainder between pixval and divN[pixval]*N
  1484.  *    magic:        Magic square for dithering to N sublevels.
  1485.  * (global) dith_size = magic square size chosen.
  1486.  * Assumptions:
  1487.  *     
  1488.  * Algorithm:
  1489.  *    divN[pixval] = (int)(pixval / N) maps pixval to its appropriate level.
  1490.  *    modN[pixval] = pixval - (int)(N * divN[pixval]) maps pixval to
  1491.  *    its sublevel, and is used in the dithering computation.
  1492.  */
  1493. void
  1494. make_square( N, divN, modN, magic )
  1495. double N;
  1496. int divN[256];
  1497. int modN[256];
  1498. int magic[16][16] ;
  1499. {
  1500.     register int i, j, k, l;
  1501.     double magicfact;
  1502.  
  1503.     for ( i = 0; i < 256; i++ )
  1504.     {
  1505.     divN[i] = (int)(i / N);
  1506.     modN[i] = i - (int)(N * divN[i]);
  1507.     }
  1508.     modN[255] = 0;        /* always */
  1509.  
  1510.     /* figure out how big a square will give */
  1511.     /* the desired number of levels */
  1512.     if(dith_np2)
  1513.         for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size++ );
  1514.     else
  1515.         for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size *=2);
  1516.  
  1517.     /* make the basic square up */
  1518.     /* ( will have numbers 0 - size * size ) */
  1519.     make_magic(dith_size,magic);
  1520.     
  1521.     /* divN gives 0 - levels-1 */
  1522.     /* modN gives 0 - N-1 */
  1523.     /* dither is if(modN(pix) > magic[][] so */
  1524.     /* scale magic it to have levels 0 to N-2 */
  1525.     /* (ie takes account of magic square size allows size * size +1 levels */
  1526.  
  1527.     magicfact = (N-2)/((double)((dith_size * dith_size)-1));
  1528.     for(i=0;i<dith_size;i++)
  1529.     {
  1530.         for(j=0;j<dith_size;j++)
  1531.         {
  1532.             magic[i][j] = (int)(0.5 + magic[i][j] * magicfact);
  1533.         }
  1534.     }
  1535.  
  1536.     if(!dith_np2)    /* if we have power of 2 */
  1537.     {
  1538.         /* now replicate the size square we've chosen */  
  1539.         /* (and use a brick pattern) */
  1540.         for(k=0;k<16;k += dith_size)
  1541.         {
  1542.             for(l=k>0?0:dith_size;l<16;l += dith_size)
  1543.             {
  1544.                 for(i=0;i<dith_size;i++)
  1545.                 {
  1546.                     for(j=0;j<dith_size;j++)
  1547.                     {
  1548.                         magic[k+i][((l+k/2)+j)%16] = magic[i][j];
  1549.                     }
  1550.                 }
  1551.             }
  1552.         }
  1553.     }
  1554. }
  1555.  
  1556. int magic16x16[16][16] = 
  1557.     {
  1558.         {0,128,32,160,8,136,40,168,2,130,34,162,10,138,42,170},
  1559.         {192,64,224,96,200,72,232,104,194,66,226,98,202,74,234,106},
  1560.         {48,176,16,144,56,184,24,152,50,178,18,146,58,186,26,154},
  1561.         {240,112,208,80,248,120,216,88,242,114,210,82,250,122,218,90},
  1562.         {12,140,44,172,4,132,36,164,14,142,46,174,6,134,38,166},
  1563.         {204,76,236,108,196,68,228,100,206,78,238,110,198,70,230,102},
  1564.         {60,188,28,156,52,180,20,148,62,190,30,158,54,182,22,150},
  1565.         {252,124,220,92,244,116,212,84,254,126,222,94,246,118,214,86},
  1566.         {3,131,35,163,11,139,43,171,1,129,33,161,9,137,41,169},
  1567.         {195,67,227,99,203,75,235,107,193,65,225,97,201,73,233,105},
  1568.         {51,179,19,147,59,187,27,155,49,177,17,145,57,185,25,153},
  1569.         {243,115,211,83,251,123,219,91,241,113,209,81,249,121,217,89},
  1570.         {15,143,47,175,7,135,39,167,13,141,45,173,5,133,37,165},
  1571.         {207,79,239,111,199,71,231,103,205,77,237,109,197,69,229,101},
  1572.         {63,191,31,159,55,183,23,151,61,189,29,157,53,181,21,149},
  1573.         {255,127,223,95,247,119,215,87,253,125,221,93,245,117,213,85}
  1574.     };
  1575.  
  1576. /*****************************************************************
  1577.  * TAG( make_magic )
  1578.      * 
  1579.  * Create the magic square.
  1580.  * Inputs:
  1581.  *     size:        Order of the square
  1582.  *  magic:        Address of 16 x 16 magic square.
  1583.  * Outputs:
  1584.  *     Fills in the 16 x 16 magic square.
  1585.  * Assumptions:
  1586.  *     size is between 2 and 16
  1587.  * Algorithm:
  1588.  *     Chose sub cell of 16 by 16 magic square
  1589.      */
  1590. make_magic( size, magic )
  1591. int size;
  1592. int magic[16][16];
  1593. {
  1594.     int j,i,li,bi,bx,by;
  1595.     int xx,yy;
  1596.     int total;
  1597.  
  1598.     total = size * size;
  1599.  
  1600.     i = 0;
  1601.     li = -1;
  1602.     for(j=0;j<total;j++)    
  1603.     {
  1604.         bi = 256;
  1605.  
  1606.         for(xx=0;xx<size;xx++)
  1607.         {
  1608.             for(yy=0;yy<size;yy++)
  1609.             {
  1610.                 if(magic16x16[xx][yy] >li && magic16x16[xx][yy] < bi)
  1611.                 {
  1612.                     bx = xx;
  1613.                     by = yy;
  1614.                     bi = magic16x16[xx][yy];
  1615.                 }
  1616.             }
  1617.         }
  1618.         magic[bx][by] = i;
  1619.         i++;
  1620.         li = bi;
  1621.     }
  1622. }
  1623.  
  1624. /*****************************************************************
  1625.  * TAG( make_gamma )
  1626.  * 
  1627.  * Makes a gamma compenstation map.
  1628.  * Inputs:
  1629.  *  gamma:            desired gamma
  1630.  *     gammamap:        gamma mapping array
  1631.  * Outputs:
  1632.  *  Changes gamma array entries.
  1633.  */
  1634. make_gamma( gamma, gammamap )
  1635. double gamma;
  1636. int gammamap[256];
  1637. {
  1638.     register int i;
  1639.  
  1640.     for ( i = 0; i < 256; i++ )
  1641.         {
  1642. #ifdef BYTEBUG
  1643.         int byteb1;
  1644.         
  1645.         byteb1 = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  1646.         gammamap[i] = byteb1;
  1647. #else
  1648.         gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  1649. #endif
  1650.         }
  1651. }
  1652.  
  1653. /*****************************************************************
  1654.  * TAG( dithergb )
  1655.  * 
  1656.  * Return dithered RGB value.
  1657.  * Inputs:
  1658.  *     x:        X location on screen of this pixel.
  1659.  *    y:        Y location on screen of this pixel.
  1660.  *    r, g, b:    Color at this pixel (0 - 255 range).
  1661.  *    levels:        Number of levels in this map.
  1662.  *    divN, modN:    From dithermap.
  1663.  *    magic:        Magic square from dithermap.
  1664.  * Outputs:
  1665.  *     Returns color map index for dithered pixelv value.
  1666.  * Assumptions:
  1667.  *     divN, modN, magic were set up properly.
  1668.  * Algorithm:
  1669.  *     see "Note:" in dithermap comment.
  1670.  */
  1671. dithergb( x, y, r, g, b, levels, divN, modN, magic )
  1672. int divN[256];
  1673. int modN[256];
  1674. int magic[16][16];
  1675. {
  1676.     int col = x % 16, row = y % 16;
  1677.  
  1678.     return DMAP(r, col, row) +
  1679.     DMAP(g, col, row) * levels +
  1680.         DMAP(b, col, row) * levels*levels;
  1681. }
  1682.  
  1683.  
  1684. /*****************************************************************
  1685.  * TAG( ditherbw )
  1686.  * 
  1687.  * Return dithered black & white value.
  1688.  * Inputs:
  1689.  *     x:        X location on screen of this pixel.
  1690.  *    y:        Y location on screen of this pixel.
  1691.  *    val:        Intensity at this pixel (0 - 255 range).
  1692.  *    divN, modN:    From dithermap.
  1693.  *    magic:        Magic square from dithermap.
  1694.  * Outputs:
  1695.  *     Returns color map index for dithered pixel value.
  1696.  * Assumptions:
  1697.  *     divN, modN, magic were set up properly.
  1698.  * Algorithm:
  1699.  *     see "Note:" in bwdithermap comment.
  1700.  */
  1701. ditherbw( x, y, val, divN, modN, magic )
  1702. int divN[256];
  1703. int modN[256];
  1704. int magic[16][16];
  1705. {
  1706.     int col = x % 16, row = y % 16;
  1707.  
  1708.     return DMAP(val, col, row);
  1709. }
  1710.